// 文件名：ecs_component_pool.cpp
// 目的：演示基于“结构分离（SoA, Structure of Arrays）”的简单 ECS 组件池：
//   - 使用两个并行的 std::vector 分别存储 Position 与 Velocity 组件；
//   - createEntity 以相同下标写入两个组件数组，并返回实体 ID（即下标）；
//   - update 按 v = dx/dt 的欧拉积分更新位置：p += v * dt。
// 说明：
//   - SoA 相比 AoS（结构数组）在遍历单一组件时更具缓存友好性；本例 update 只读写
//     positions 与 velocities 的线性内存，顺序访问命中率较高。
//   - 实体 ID 即数组下标；要求两个数组始终等长且下标对齐（第 i 个 Position 对应第 i 个 Velocity）。
//   - 本示例未实现删除实体。如需删除，常见做法是“swap-pop”：将末尾元素交换到待删位置，并 pop_back，
//     同时保持两个数组同步交换，避免产生空洞与移动大量元素。
//   - 若实体数量大，可在创建前 reserve 以减少扩容；update 可并行化（分片或使用并行算法/线程池）。
//   - dt 表示时间步长（秒）。固定时间步（fixed timestep）通常更稳定；可采用累积器策略实现渲染与物理解耦。

#include <vector>
#include <iostream>

struct Position {
    float x, y, z; // 位置分量（单位：米，或任意世界坐标单位）
};

struct Velocity {
    float vx, vy, vz; // 速度分量（单位：米/秒）
};

class MovementSystem {
public:
    // 创建一个实体：在 positions 与 velocities 两个池中各推入一个组件
    // 返回：实体 ID（即数组下标）
    // 注意：
    //   - 需保证两个数组始终长度一致；本示例逻辑保证 emplace_back 成对调用。
    //   - 大量创建前可调用 positions.reserve(N)、velocities.reserve(N) 以减少重分配。
    std::size_t createEntity(Position p, Velocity v) {
        positions.emplace_back(p);
        velocities.emplace_back(v);
        return positions.size() - 1; // 实体 ID：最后一个元素的下标
    }

    // 更新所有实体的位置：p += v * dt
    // 复杂度：O(n)，n 为实体数
    // 说明：
    //   - 欧拉积分法（显式）：简单但对大 dt 可能不稳定；必要时可用半隐式/Runge-Kutta 等更稳健的方法。
    //   - 这里假设 positions 与 velocities 数量一致；实际工程可添加断言或防御式检查。
    void update(float dt) {
        // 简单的线性遍历，缓存友好；可按需并行化（如 OpenMP、std::execution、任务分片等）
        for (std::size_t i = 0; i < positions.size(); ++i) {
            positions[i].x += velocities[i].vx * dt;
            positions[i].y += velocities[i].vy * dt;
            positions[i].z += velocities[i].vz * dt;
        }
    }

    // 组件池（SoA）：并行向量，索引对齐
    std::vector<Position> positions;
    std::vector<Velocity> velocities;
};

int main() {
    MovementSystem system;

    // 创建两个实体：给定初始位置与速度
    system.createEntity({0.f, 0.f, 0.f},   {1.f,   0.5f, 0.2f});
    system.createEntity({-2.f, 1.f, 0.f},  {0.3f,  0.1f, 0.f});

    // 使用约 60 FPS 的步长更新（dt ≈ 0.16s）
    system.update(0.16f);

    // 打印所有实体的位置，验证更新结果
    for (std::size_t i = 0; i < system.positions.size(); ++i) {
        const auto& p = system.positions[i];
        std::cout << "Entity " << i << " position: (" << p.x << ", "
                  << p.y << ", " << p.z << ")\n";
    }
    return 0;
}